#ifndef MSLOG_INNER_H
#define MSLOG_INNER_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<pthread.h> 
#include "mstype.h"
/*----------------------------------------------*
 * enum											*
 *----------------------------------------------*/
typedef enum {
	mslog_level_assert=0x00,
   	mslog_level_error,
   	mslog_level_warn,
   	mslog_level_info,
   	mslog_level_debug,
   	mslog_level_verbose,
   	mslog_level_more,
   	ENUM_LOG_LEVEL_MAX
}ENLOGLevel;

#if defined(OS_LINUX_SOC)
#define ms_csc_none		"\e[0m"
#define ms_csc_black                	"\e[0;30m"
#define ms_csc_lblack              	"\e[1;30m"
#define ms_csc_red 		"\e[0;31m"
#define ms_csc_lred 		"\e[1;31m"
#define ms_csc_green 		"\e[0;32m"
#define ms_csc_lgreen 		"\e[1;32m"
#define ms_csc_brown		"\e[0;33m"
#define ms_csc_lyellow		"\e[1;33m"
#define ms_csc_blue		"\e[0;34m"
#define ms_csc_lblue		"\e[1;34m"
#define ms_csc_purple		"\e[0;35m"
#define ms_csc_lpurple		"\e[1;35m"
#define ms_csc_cyan		"\e[0;36m"
#define ms_csc_lcyan		"\e[1;36m"
#define ms_csc_gray		"\e[0;37m"
#define ms_csc_white		"\e[1;37m"

#define BOLD                 	"\e[1m"
#define UNDERLINE         "\e[4m"
#define REVERSE              	"\e[7m"

static const ms_string ms_col[64]={
	ms_csc_lblue,		//assert
	ms_csc_lred,		//error
	ms_csc_lyellow,	//waring
	ms_csc_lcyan,		//info
	ms_csc_none,		//debug
	ms_csc_green,		//verbose
	ms_csc_gray};	//more
#else
#define ms_csc_none   ""           
static const ms_string ms_col[64]={
	"",	//assert
	"",	//error
	"",	//waring
	"",	//info
	"",	//debug
	"",	//verbose
	""};	//more
#endif
/*----------------------------------------------*
 * macros �궨��                                *
 *----------------------------------------------*/
#define DEFAULT_LOG_LEVEL  ENUM_LOG_LEVEL_MAX

#ifndef MSLOG_C 
#define INTERFACE_LOG extern
#else
#define INTERFACE_LOG 
#endif
INTERFACE_LOG ms_void    mslog_innerapi_filewrite(ms_pbyte ms_in buf, ms_u32 ms_in size);
INTERFACE_LOG ms_string mslog_innerapi_systimedate_filelog(ms_void);
INTERFACE_LOG ms_string mslog_innerapi_systimedate_nor(ms_void);
INTERFACE_LOG ms_void    mslog_innerapi_buf( ms_string ms_in description,ms_pu08 ms_in buf, ms_u32 ms_in len,ms_cstring ms_in func,ms_u32 ms_in line);
INTERFACE_LOG ms_void    mslog_innerapi_bufandascii( ms_string ms_in description,ms_pu08 ms_in buf, ms_u32 ms_in len,ms_cstring ms_in func,ms_u32 ms_in line);
INTERFACE_LOG ms_void    mslog_innerapi_errbuf( ms_string ms_in description,ms_pu08 ms_in buf, ms_u32 ms_in len,ms_cstring ms_in func,ms_u32 ms_in line);
INTERFACE_LOG ms_void    mslog_innerapi_bufascii( ms_string ms_in description,ms_pu08 ms_in buf, ms_u32 ms_in len,ms_cstring ms_in func,ms_u32 ms_in line);
INTERFACE_LOG ms_u32     mslog_innerapi_getloglevel(ms_void);
INTERFACE_LOG ms_bool 	mslog_inner_linefunc;
INTERFACE_LOG ms_bool 	mslog_inner_nor;
INTERFACE_LOG ms_bool 	mslog_inner_file;
INTERFACE_LOG ms_pbyte  	mslogfile_buf;
INTERFACE_LOG ms_u32 	mslogfile_buf_maxlen;	
INTERFACE_LOG pthread_mutex_t mslogfile_mutex;
INTERFACE_LOG const ms_string astring_loglevel[32];
#define LINE_FMT		"[%s %s %d]"
#define LINE_ARG		__FILE__,__FUNCTION__, __LINE__
#define ARG			"\r\n"
#define LOGLEVE_FMT	"[%s]"

#define PRINT printf
#define LOG_DBG( level, flag , fmt, arg...)\
	if ( !(level >  mslog_innerapi_getloglevel()) ){\
		if(mslog_inner_linefunc) { \
			if(mslog_inner_file){ \
				pthread_mutex_lock(&mslogfile_mutex); \
				memset(mslogfile_buf,0,mslogfile_buf_maxlen);\
				snprintf(mslogfile_buf,mslogfile_buf_maxlen,"%s"LOGLEVE_FMT"["flag"]"  LINE_FMT   fmt ARG,mslog_innerapi_systimedate_filelog(),astring_loglevel[level],LINE_ARG,##arg);\
				mslog_innerapi_filewrite(mslogfile_buf ,strlen(mslogfile_buf)); \
				pthread_mutex_unlock(&mslogfile_mutex); \
			} \
			if(mslog_inner_nor) {PRINT("%s %s"LOGLEVE_FMT"["flag"]"  LINE_FMT  fmt ms_csc_none ARG,ms_col[level],mslog_innerapi_systimedate_nor(),astring_loglevel[level],LINE_ARG,##arg );}\
		}else{\
			if(mslog_inner_file){ \
				pthread_mutex_lock(&mslogfile_mutex); \
				memset(mslogfile_buf,0,mslogfile_buf_maxlen); \
				snprintf(mslogfile_buf,mslogfile_buf_maxlen,"%s"LOGLEVE_FMT"["flag"]"   fmt ARG,mslog_innerapi_systimedate_filelog(),astring_loglevel[level],##arg); \
				mslog_innerapi_filewrite(mslogfile_buf ,strlen(mslogfile_buf)); \
				pthread_mutex_unlock(&mslogfile_mutex); \
			} \
			if(mslog_inner_nor) {PRINT("%s %s"LOGLEVE_FMT"["flag"]"  fmt ms_csc_none ARG,ms_col[level],mslog_innerapi_systimedate_nor(),astring_loglevel[level],##arg );} \
		} \
	}

#define LOG_DBG1( level, flag , fmt, arg...)\
	if ( !(level >  mslog_innerapi_getloglevel()) ){\
		if(mslog_inner_file) {\
			pthread_mutex_lock(&mslogfile_mutex);  \
			memset(mslogfile_buf,0,mslogfile_buf_maxlen);\
			snprintf(mslogfile_buf,mslogfile_buf_maxlen,"%s"LOGLEVE_FMT"["flag"]" fmt ,mslog_innerapi_systimedate_filelog(),astring_loglevel[level],##arg);\
			mslog_innerapi_filewrite(mslogfile_buf ,strlen(mslogfile_buf));\
			pthread_mutex_unlock(&mslogfile_mutex); \
		} \
		if(mslog_inner_nor) PRINT("%s %s"LOGLEVE_FMT"["flag"]"  fmt ms_csc_none ,ms_col[level], mslog_innerapi_systimedate_nor(),astring_loglevel[level],##arg );\
	}
	
#define LOG_DBG2( level , fmt, arg...)\
	if ( !(level >  mslog_innerapi_getloglevel()) ){\
		if(mslog_inner_file) { \
			pthread_mutex_lock(&mslogfile_mutex);  \
			memset(mslogfile_buf,0,mslogfile_buf_maxlen);\
			snprintf(mslogfile_buf,mslogfile_buf_maxlen, fmt ,##arg);\
			mslog_innerapi_filewrite(mslogfile_buf ,strlen(mslogfile_buf));\
			pthread_mutex_unlock(&mslogfile_mutex); \
		} \
		if(mslog_inner_nor) PRINT(  "%s"fmt ms_csc_none ,ms_col[level], ##arg );\
	}

#define bufcheck_noret(dbuf) \
	if(NULL==dbuf){ \
		return; \
	}

#define bufcheck(dbuf) \
	if(NULL==dbuf){ \
		ms_errnoret("dbuf is null"); \
	}
#define bufcheck_ret(ret,dbuf) \
	if(NULL==dbuf){ \
		ms_errret(ret,"dbuf is null"); \
	}
#define bufcheck_goto(gval,dbuf) \
	if(NULL==dbuf){ \
		ms_error("dbuf  is null"); \
		goto gval; \
	}

#define bufcheck_des(buf,fmt,arg...) \
	if(NULL==buf){ \
		ms_errnoret(fmt,##arg); \
	}
	
#define bufcheckret_des(ret,buf,fmt,arg...) \
	if(NULL==buf){ \
		ms_errret(ret,fmt,##arg); \
	}
	
#define bufcheck_goto_des(gval,buf,fmt,arg...) \
	if(NULL==buf){ \
		ms_error(fmt,##arg); \
		goto gval; \
	}


/*****************************************************************************
 Description  : mslog with use-flags api
*****************************************************************************/
#define ms_lfatal(flag , fmt, arg...) 		LOG_DBG( mslog_level_assert	, flag , fmt, ##arg)
#define ms_lerror(flag , fmt, arg...) 		LOG_DBG( mslog_level_error	, flag , fmt, ##arg)
#define ms_lwaring(flag , fmt, arg...) 		LOG_DBG( mslog_level_warn	, flag , fmt, ##arg)
#define ms_linfo(flag , fmt, arg...) 			LOG_DBG( mslog_level_info	, flag , fmt, ##arg)
#define ms_ldebug(flag , fmt, arg...) 		LOG_DBG( mslog_level_debug	, flag , fmt, ##arg)
#define ms_lverbose(flag , fmt, arg...) 		LOG_DBG( mslog_level_verbose, flag , fmt, ##arg)
#define ms_lmore(flag , fmt, arg...) 		LOG_DBG( mslog_level_more, flag , fmt, ##arg)

#define ms_lfatal1(flag , fmt, arg...) 		LOG_DBG1( mslog_level_assert	, flag , fmt, ##arg)
#define ms_lerror1(flag , fmt, arg...) 		LOG_DBG1( mslog_level_error	, flag , fmt, ##arg)
#define ms_lwaring1(flag , fmt, arg...) 		LOG_DBG1( mslog_level_warn	, flag , fmt, ##arg)
#define ms_linfo1(flag , fmt, arg...) 			LOG_DBG1( mslog_level_info	, flag , fmt, ##arg)
#define ms_ldebug1(flag , fmt, arg...) 		LOG_DBG1( mslog_level_debug	, flag , fmt, ##arg)
#define ms_lverbose1(flag , fmt, arg...) 		LOG_DBG1( mslog_level_verbose, flag , fmt, ##arg)
#define ms_lmore1(flag , fmt, arg...) 		LOG_DBG1( mslog_level_more, flag , fmt, ##arg)
/*****************************************************************************
 Description  : use ms_num2str(num) instread
*****************************************************************************/
INTERFACE_LOG ms_string mslog_innerapi_num2str( ms_string ms_out outstr, ms_s64 ms_in num);
INTERFACE_LOG ms_string mslog_innerapi_bitbyte64( ms_string ms_out outstr, ms_u64 ms_in num64_h, ms_u64 ms_in num64_l,ms_string punit);
INTERFACE_LOG ms_string mslog_innerapi_bitbyte32( ms_string ms_out outstr, ms_u32 ms_in num32_h, ms_u32 ms_in num32_l,ms_string punit);
#endif

